home *** CD-ROM | disk | FTP | other *** search
/ Aminet 45 / Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso / Aminet / gfx / x11 / x3270_3_2_16.lha / amiga_src / x3270if.c < prev    next >
C/C++ Source or Header  |  2009-02-19  |  7KB  |  348 lines

  1. /*
  2.  * Copyright 1995, 1996, 1999, 2000 by Paul Mattes.
  3.  *  Permission to use, copy, modify, and distribute this software and its
  4.  *  documentation for any purpose and without fee is hereby granted,
  5.  *  provided that the above copyright notice appear in all copies and that
  6.  *  both that copyright notice and this permission notice appear in
  7.  *  supporting documentation.
  8.  */
  9.  
  10. /*
  11.  * Script interface utility for x3270.
  12.  *
  13.  * Accesses an x3270 command stream on the file descriptors defined by the
  14.  * environment variables X3270OUTPUT (output from x3270, input to script) and
  15.  * X3270INPUT (input to x3270, output from script).
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <signal.h>
  21. #include <errno.h>
  22. #include <stdlib.h>
  23. #include <unistd.h>
  24. #include <fcntl.h>
  25.  
  26. #define IBS    1024
  27.  
  28. extern int optind;
  29. extern char *optarg;
  30.  
  31. static char *me;
  32. static int verbose = 0;
  33. static char buf[IBS];
  34.  
  35. static void iterative_io(void);
  36. static void single_io(int fn, char *cmd);
  37.  
  38. static void
  39. usage(void)
  40. {
  41.     (void) fprintf(stderr, "\
  42. usage: %s [-v] action[(param[,...])]\n\
  43.        %s [-v] -s field\n\
  44.        %s -i\n", me, me, me);
  45.     exit(2);
  46. }
  47.  
  48. /* Get a file descriptor from the environment. */
  49. static int
  50. fd_env(const char *name)
  51. {
  52.     char *fdname;
  53.     int fd;
  54.  
  55.     fdname = getenv(name);
  56.     if (fdname == (char *)NULL) {
  57.         (void) fprintf(stderr, "%s: %s not set in the environment\n",
  58.                 me, name);
  59.         exit(2);
  60.     }
  61.     fd = atoi(fdname);
  62.     if (fd <= 0) {
  63.         (void) fprintf(stderr, "%s: invalid value '%s' for %s\n", me,
  64.             fdname, name);
  65.         exit(2);
  66.     }
  67.     return fd;
  68. }
  69.  
  70. int
  71. main(int argc, char *argv[])
  72. {
  73.     int c;
  74.     int fn = -1;
  75.     char *ptr;
  76.     int iterative = 0;
  77.  
  78.     /* Identify yourself. */
  79.     if ((me = strrchr(argv[0], '/')) != (char *)NULL)
  80.         me++;
  81.     else
  82.         me = argv[0];
  83.  
  84.     /* Parse options. */
  85.     while ((c = getopt(argc, argv, "is:v")) != -1) {
  86.         switch (c) {
  87.             case 'i':
  88.             if (fn != -1)
  89.                 usage();
  90.             iterative++;
  91.             break;
  92.             case 's':
  93.             if (fn != -1 || iterative)
  94.                 usage();
  95.             fn = (int)strtol(optarg, &ptr, 0);
  96.             if (ptr == optarg || *ptr != '\0' || fn < 0) {
  97.                 (void) fprintf(stderr,
  98.                     "%s: Invalid field number: '%s'\n", me,
  99.                     optarg);
  100.                 usage();
  101.             }
  102.             break;
  103.             case 'v':
  104.             verbose++;
  105.             break;
  106.             default:
  107.             usage();
  108.             break;
  109.         }
  110.     }
  111.  
  112.     /* Validate positional arguments. */
  113.     if (fn != -1 || iterative) {
  114.         if (optind != argc)
  115.             usage();
  116.     } else {
  117.         if (optind != argc - 1)
  118.             usage();
  119.     }
  120.  
  121.     /* Ignore broken pipes. */
  122.     (void) signal(SIGPIPE, SIG_IGN);
  123.  
  124.     /* Do the I/O. */
  125.     if (!iterative) {
  126.         single_io(fn, argv[optind]);
  127.     } else {
  128.         iterative_io();
  129.     }
  130.     return 0;
  131. }
  132.  
  133. /* Do a single command, and interpret the results. */
  134. static void
  135. single_io(int fn, char *cmd)
  136. {
  137.     FILE *inf = NULL, *outf = NULL;
  138.     char status[IBS] = "";
  139.     int xs = -1;
  140.  
  141.     /* Verify the environment and open files. */
  142.     inf = fdopen(fd_env("X3270OUTPUT"), "r");
  143.     if (inf == (FILE *)NULL) {
  144.         perror("x3270if: input: fdopen($X3270OUTPUT)");
  145.         exit(2);
  146.     }
  147.     outf = fdopen(fd_env("X3270INPUT"), "w");
  148.     if (outf == (FILE *)NULL) {
  149.         perror("x3270if: output: fdopen($X3270INPUT)");
  150.         exit(2);
  151.     }
  152.  
  153.     /* Speak to x3270. */
  154.     if (fprintf(outf, "%s\n", (fn == -1)? cmd: "") < 0 ||
  155.         fflush(outf) < 0) {
  156.         perror("x3270if: printf");
  157.         exit(2);
  158.     }
  159.     if (verbose)
  160.         (void) fprintf(stderr, "i+ out %s\n",
  161.             (fn == -1) ? cmd : "");
  162.  
  163.     /* Get the answer. */
  164.     while (fgets(buf, IBS, inf) != (char *)NULL) {
  165.         int sl = strlen(buf);
  166.  
  167.         if (sl > 0 && buf[sl-1] == '\n')
  168.             buf[--sl] = '\0';
  169.         if (verbose)
  170.             (void) fprintf(stderr, "i+ in %s\n", buf);
  171.         if (!strcmp(buf, "ok")) {
  172.             (void) fflush(stdout);
  173.             xs = 0;
  174.             break;
  175.         } else if (!strcmp(buf, "error")) {
  176.             (void) fflush(stdout);
  177.             xs = 1;
  178.             break;
  179.         } else if (!strncmp(buf, "data: ", 6)) {
  180.             if (printf("%s\n", buf+6) < 0) {
  181.                 perror("x3270if: printf");
  182.                 exit(2);
  183.             }
  184.         } else
  185.             (void) strcpy(status, buf);
  186.     }
  187.  
  188.     /* If fgets() failed, so should we. */
  189.     if (xs == -1) {
  190.         if (feof(inf))
  191.             (void) fprintf(stderr,
  192.                     "x3270if: input: unexpected EOF\n");
  193.         else
  194.             perror("x3270if: input");
  195.         exit(2);
  196.     }
  197.  
  198.     if (fflush(stdout) < 0) {
  199.         perror("x3270if: fflush");
  200.         exit(2);
  201.     }
  202.  
  203.     /* Print status, if that's what they want. */
  204.     if (fn != -1) {
  205.         char *sf = (char *)NULL;
  206.         char *sb = status;
  207.  
  208.         do {
  209.             if (!fn--)
  210.                 break;
  211.             sf = strtok(sb, " \t");
  212.             sb = (char *)NULL;
  213.         } while (sf != (char *)NULL);
  214.         if (printf("%s\n", (sf != (char *)NULL) ? sf : "") < 0) {
  215.             perror("x3270if: printf");
  216.             exit(2);
  217.         }
  218.     }
  219.  
  220.     if (fflush(stdout) < 0) {
  221.         perror("x3270if: fflush");
  222.         exit(2);
  223.     }
  224.  
  225.     exit(xs);
  226. }
  227.  
  228. /* Act as a passive pipe between 'expect' and x3270. */
  229. static void
  230. iterative_io(void)
  231. {
  232. #    define N_IO 2
  233.     struct {
  234.         const char *name;
  235.         int rfd, wfd;
  236.         char buf[IBS];
  237.         int offset, count;
  238.     } io[N_IO];    /* [0] is program->x3270, [1] is x3270->program */
  239.     fd_set rfds, wfds;
  240.     int fd_max = 0;
  241.     int i;
  242.  
  243. #ifdef DEBUG
  244.     if (verbose) {
  245.         freopen("/tmp/x3270if.dbg", "w", stderr);
  246.         setlinebuf(stderr);
  247.     }
  248. #endif
  249.  
  250.     /* Get the x3270 file descriptors. */
  251.     io[0].name = "program->x3270";
  252.     io[0].rfd = fileno(stdin);
  253.     io[0].wfd = fd_env("X3270INPUT");
  254.     io[1].name = "x3270->program";
  255.     io[1].rfd = fd_env("X3270OUTPUT");
  256.     io[1].wfd = fileno(stdout);
  257.     for (i = 0; i < N_IO; i++) {
  258.         if (io[i].rfd > fd_max)
  259.             fd_max = io[i].rfd;
  260.         if (io[i].wfd > fd_max)
  261.             fd_max = io[i].wfd;
  262.         (void) fcntl(io[i].rfd, F_SETFL,
  263.             fcntl(io[i].rfd, F_GETFL, 0) | O_NDELAY);
  264.         (void) fcntl(io[i].wfd, F_SETFL,
  265.             fcntl(io[i].wfd, F_GETFL, 0) | O_NDELAY);
  266.         io[i].offset = 0;
  267.         io[i].count = 0;
  268.     }
  269.     fd_max++;
  270.  
  271.     for (;;) {
  272.         int rv;
  273.  
  274.         FD_ZERO(&rfds);
  275.         FD_ZERO(&wfds);
  276.  
  277.         for (i = 0; i < N_IO; i++) {
  278.             if (io[i].count) {
  279.                 FD_SET(io[i].wfd, &wfds);
  280. #ifdef DEBUG
  281.                 if (verbose)
  282.                     (void) fprintf(stderr,
  283.                         "enabling output %s %d\n",
  284.                         io[i].name, io[i].wfd);
  285. #endif
  286.             } else {
  287.                 FD_SET(io[i].rfd, &rfds);
  288. #ifdef DEBUG
  289.                 if (verbose)
  290.                     (void) fprintf(stderr,
  291.                         "enabling input %s %d\n",
  292.                         io[i].name, io[i].rfd);
  293. #endif
  294.             }
  295.         }
  296.  
  297.         if ((rv = select(fd_max, &rfds, &wfds, (fd_set *)NULL,
  298.                 (struct timeval *)NULL)) < 0) {
  299.             perror("x3270if: select");
  300.             exit(2);
  301.         }
  302.         if (verbose)
  303.             (void) fprintf(stderr, "select->%d\n", rv);
  304.  
  305.         for (i = 0; i < N_IO; i++) {
  306.             if (io[i].count) {
  307.                 if (FD_ISSET(io[i].wfd, &wfds)) {
  308.                     rv = write(io[i].wfd,
  309.                         io[i].buf + io[i].offset,
  310.                         io[i].count);
  311.                     if (rv < 0) {
  312.                         (void) fprintf(stderr,
  313.                             "x3270if: write(%s): %s",
  314.                             io[i].name,
  315.                             strerror(errno));
  316.                         exit(2);
  317.                     }
  318.                     io[i].offset += rv;
  319.                     io[i].count -= rv;
  320. #ifdef DEBUG
  321.                     if (verbose)
  322.                         (void) fprintf(stderr,
  323.                             "write(%s)->%d\n",
  324.                             io[i].name, rv);
  325. #endif
  326.                 }
  327.             } else if (FD_ISSET(io[i].rfd, &rfds)) {
  328.                 rv = read(io[i].rfd, io[i].buf, IBS);
  329.                 if (rv < 0) {
  330.                     (void) fprintf(stderr,
  331.                         "x3270if: read(%s): %s",
  332.                         io[i].name, strerror(errno));
  333.                     exit(2);
  334.                 }
  335.                 if (rv == 0)
  336.                     exit(0);
  337.                 io[i].offset = 0;
  338.                 io[i].count = rv;
  339. #ifdef DEBUG
  340.                 if (verbose)
  341.                     (void) fprintf(stderr,
  342.                         "read(%s)->%d\n", io[i].name, rv);
  343. #endif
  344.             }
  345.         }
  346.     }
  347. }
  348.